package bdz.projects.lavender.doi.model
{
	import bdz.common.display.DisplayLoader;
	import bdz.common.events.XMLLoaderEvent;
	import bdz.common.managers.ModuleAssetManager;
	import bdz.common.model.AppEnvironment;
	
	import flash.events.EventDispatcher;
	import flash.media.Sound;
	import flash.utils.Dictionary;
	
	

	public class DOIShellReader extends EventDispatcher
	{
		private static var instance:DOIShellReader;
		private static var _config:Object;
		private var _loadedInfo:Dictionary;
		private var _assets:Dictionary;
		private var _queuedData:String;
		private var _queuedAsset:String;
		private var _connector:DOIConnector;
		private var _queuedCallback:Dictionary;
		private var _moduleProps:Array;
		private var _stepProps:Array;
		private var _assetManager:ModuleAssetManager;
		
		private var env:AppEnvironment = AppEnvironment.getEnv();
		public function DOIShellReader(se:SingletonEnforcer)
		{
			super();
		}
		private function initialize(cfg:Object):void {
			_moduleProps = ["description", "definition", "otherheader", "otherdescription", "voiceover", "animation"]
			_stepProps = ["definition", "description", "htmlimage", "audiourl", "swfimage"];
			_loadedInfo = new Dictionary();
			_assets = new Dictionary();
			_queuedCallback = new Dictionary();
			_config = cfg;
			_connector = DOIConnector.getInstance(cfg);
		}
		
		private function convertAllToArray(xm:XMLList):Array {
			var ret:Array = new Array();
			var len:Number = xm.length();
			for (var i:Number = 0; i < len; i++) {
				var o:Object = { };
				o.index = i;
				var attlist:XMLList = xm[i].@ * ;
				for each(var atts:* in attlist) {
					o[atts.name().toString()] = atts.toString();
				}
				o.definition = xm[i].definition;
				o.type = "category";
				o.subtype = "modules";
				if (xm[i].module.length()) {
					o.modules = convertModulesToArray(xm[i].module, "steps", o);
				}
				ret.push(o);
			}
			
			return ret;
		}
		private function convertCategoriesToArray(xm:XMLList):Array {
			var ret:Array = new Array();
			var len:Number = xm.length();
			for (var i:Number = 0; i < len; i++) {
				var o:Object = { };
				var attlist:XMLList = xm[i].@ * ;
				for each(var atts:* in attlist) {
					o[atts.name().toString()] = atts.toString();
				}
				o.index = i;
				o.definition = xm[i].definition;
				ret.push(o);
			}
			//ret.sortOn("order");
			return ret;
		}
		private function convertStepsToArray(xm:XMLList, prnt:Object):Array {
			var ret:Array = new Array();
			var len:Number = xm.length();
			for (var i:Number = 0; i < len; i++) {
				ret[i] = { };
				ret[i].index = i;
				ret[i].parent = prnt;
				ret[i].id = String(xm[i].@id);
				ret[i].name = String(xm[i].@name);
				ret[i].shortname = String(xm[i].@shortname);
				for each(var str:String in _stepProps) {
					ret[i][str] = xm[i][str].toString();
				}
				ret[i].type = "chapter";
			}
			//ret.sortOn("order");
			return ret;
		}
		private function convertModulesToArray(xm:XMLList, prop:String = "steps", prnt:Object = null):Array {
			
			var ret:Array = new Array();
			var len:Number = xm.length();
			for (var i:Number = 0; i < len; i++) {
				ret[i] = { };
				ret[i].index = i;
				ret[i].id = String(xm[i].@id);
				ret[i].name = String(xm[i].@name);
				ret[i].shortname = String(xm[i].@shortname);
				ret[i].order = Number(xm[i].@order);
				ret[i].parent = prnt;
				for each(var str:String in _moduleProps) {
					ret[i][str] = xm[i][str].toString();
				}
				ret[i].type = "module";
				ret[i].subtype = prop;
				ret[i][prop] = convertStepsToArray(xm[i].step, ret[i]);
			}
			//ret.sortOn("order");
			return ret;
		}
		private function convertCaptionsToArray(xlist:XMLList):Array {
			var arr:Array = new Array();
			for each(var xm:XML in xlist) {
				var o = { };
				var chl:XMLList = xm.children();
				for each(var xc:XML in chl) {
					o[xc.name()] = Number(xc.toString()) ? Number(xc.toString()) : xc.toString();
				}
				arr.push(o);
			}
			return arr;
		}
		private function convertGlobalToObject(xlist:XMLList ):Object {
			var o:Object = { };
			for each(var xm:XML in xlist) {
				
				if (xm.name() != "caption") {
					o[xm.name()] = xm.toString();
				}else {
					o[xm.name()] = convertCaptionsToArray(new XML(xm.toString()).caption)
				}
			}
			return o;
		}
		private function allLoaded(evt:XMLLoaderEvent):void {
			
			_loadedInfo["all"] = convertAllToArray(new XML(evt.data).category);
			_queuedCallback["all"](_loadedInfo["all"]);
		}
		private function categoriesLoaded(evt:XMLLoaderEvent):void {
			
			_loadedInfo["categories"] = convertCategoriesToArray(new XML(evt.data).category);
			_queuedCallback["categories"](_loadedInfo["categories"]);
		}
		private function globalLoaded(evt:XMLLoaderEvent):void {
			
			_loadedInfo["doi_global"] = convertGlobalToObject(new XML(evt.data).children());
			_queuedCallback["doi_global"](_loadedInfo["doi_global"]);
		}
		private function catModulesLoaded(evt:XMLLoaderEvent):void {
			var xm:XML = new XML(evt.data);
			_loadedInfo[String(xm.category.@id)] = convertModulesToArray(xm.category.module);
			_queuedCallback[String(xm.category.@id)](_loadedInfo[String(xm.category.@id)]);
		}
		public static function getReader(cfg:Object):DOIShellReader{
			if(!instance){
				instance = new DOIShellReader(new SingletonEnforcer());
				instance.initialize(cfg);
			}
			return instance;
		}
		public function getAll(callback:Function):void {
			if (_loadedInfo["all"]) {
				callback(_loadedInfo["all"]);
			}else {
				_queuedCallback["all"] = callback;
				_connector.getAll(allLoaded);
			}
			
		}
		public function getAllCategories(callback:Function):void {
			if (_loadedInfo["categories"]) {
				callback(_loadedInfo["categories"]);
			}else {
				_queuedCallback["categories"] = callback;
				_connector.getAllCategories(categoriesLoaded);
			}
		}		
		public function getModules(cid:String, callback:Function):void {
			if (_loadedInfo[cid]) {
				callback(_loadedInfo[cid]);
			}else {
				_queuedCallback[cid] = callback;
				_connector.getCategoryContents(cid, catModulesLoaded);
			}
		}
		public function getGlobalValues(callback:Function):void {
			if (_loadedInfo["doi_global"]) {
				callback(_loadedInfo["doi_global"]);
			}else {
				_queuedCallback["doi_global"] = callback;
				_connector.getGlobalValues(globalLoaded);
			}
		}
		public function getSoundAsset(_url:String, callback:Function):Sound {
			return new Sound();
		}
		public function getViewAsset(_url:String, callback:Function):DisplayLoader {
			
			return new DisplayLoader();
		}
		public static function get CONFIGURATION():Object {
			return _config;
		}
		
		
	}
}
/**
 * @private
 * 
 */
internal class SingletonEnforcer{}